﻿using mozhi.smarterp.Business.Enums;
using mozhi.smarterp.Business.Sales.Repositories;
using Mozhi.Abp.Domain.AuthorCenter;
using Mozhi.Abp.Domain.BasicData;
using Mozhi.Abp.Domain.BasicData.Repositories;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Guids;

namespace mozhi.smarterp.Business.Sales.Services
{
    public class SaleQuotationManager : DocumentManagerBase<SaleQuotation , Guid>
    {
        private ICustomerRepository _customerRepository;
        private IEmployeeRepository _employeeRepository;
        private ICurrencyRepository _currencyRepository;
        private IDepartmentRepository _departmentRepository;
        private IProductAuxiliaryUnitRepository _auxiliaryUnitRepository;
        private IProductRepository _productRepository;
        private ITaxRateRepository _taxRateRepository;
        private IUnitRepository _unitRepository;
        private IGuidGenerator _guidGenerator;
        private ISaleQuotationOrderRepository _quotationOrderRepository;
        private SaleOrderManager _orderManager;
        private ISaleOrderRepository _orderRepository;

        public SaleQuotationManager(ISaleQuotationRepository repository, IGuidGenerator guidGenerator, IEmployeeRepository employeeRepository, ICurrencyRepository currencyRepository, IDepartmentRepository departmentRepository , 
            INumberGeneratorRepository numberGeneratorRepository  , IProductRepository productRepository , ITaxRateRepository taxRateRepository , IProductAuxiliaryUnitRepository auxiliaryUnitRepository , 
            IUnitRepository unitRepository , ISaleQuotationOrderRepository quotationOrderRepository , SaleOrderManager orderManager , ISaleOrderRepository orderRepository)
            :base(repository, numberGeneratorRepository , DocumentType.SaleQuotation)
        {
            _guidGenerator = guidGenerator;
            _employeeRepository = employeeRepository;
            _currencyRepository = currencyRepository;
            _departmentRepository = departmentRepository;
            _taxRateRepository = taxRateRepository;
            _productRepository = productRepository;
            _auxiliaryUnitRepository = auxiliaryUnitRepository;
            _unitRepository = unitRepository;
            _quotationOrderRepository = quotationOrderRepository;
            _orderManager = orderManager;
            _orderRepository = orderRepository;
        }

        public async Task<SaleQuotation> GetAsync(Guid? id, DateTime date, bool includeTax, Guid customerId, string address, Guid currencyId, decimal exchangeRate, Guid? departmentId, Guid? salePersonId,
            DateTime? effectiveDate, DateTime? expirationDate, string comment, SaleQuotationType type)
        {
            var customer = await _customerRepository.GetAsync(customerId);
            var currency = await _currencyRepository.GetAsync(currencyId);
            var department = departmentId.HasValue ?  await _departmentRepository.GetAsync(departmentId.Value) : null;
            var salePerson = salePersonId.HasValue ? await _employeeRepository.GetAsync(salePersonId.Value) : null;

            currency.SetExchangeRate(exchangeRate);

            SaleQuotation saleQuotation;

            if (id.HasValue)
            {
                saleQuotation = await _repository.GetAsync(id.Value);

                saleQuotation.Change(saleQuotation.Number, date, includeTax, customer, address, currency, exchangeRate, department, salePerson, effectiveDate, expirationDate, comment, type);
            }
            else
            {
                var number = await GetNextNumberAsync();
                saleQuotation = new SaleQuotation(_guidGenerator.Create(), number, date, includeTax, customer, address, currency, exchangeRate, department, salePerson, effectiveDate, expirationDate, comment, type);
            }

            return saleQuotation;
        }

        public async Task<SaleQuotationItem> GetItemAsync(Guid? id, Guid productId, Guid saleUnitId, decimal saleQuantity, decimal price, Guid? taxRateId, bool isGift, string remark)
        {
            var product = await _productRepository.GetAsync(productId);

            var productAuxiliaryUnit = saleUnitId == product.BasicUnitId ? null : await _auxiliaryUnitRepository.GetAsync(productId, saleUnitId);

            var saleUnit = await _unitRepository.GetAsync(saleUnitId);

            var taxRate = taxRateId.HasValue ? await _taxRateRepository.GetAsync(taxRateId.Value) : null;

            id = id ?? _guidGenerator.Create();

            var item = new SaleQuotationItem(id.Value, product, saleUnit, productAuxiliaryUnit, saleQuantity, price, taxRate, isGift, remark);

            return item;
        }

        public async Task<SaleQuotation> UpdateStatusAsync(Guid id , DocumentStatusType status)
        {
            var quotation = await _repository.GetAsync(id, true);

            if (quotation == null)
                throw new UserFriendlyException($"销售报价单：{id}不存在", "100000");

            if (quotation.Status == DocumentStatusType.Approved && status == DocumentStatusType.PendingApproval)
            {
                //反审核操作，需要校验是否关联了销售订单
                var orderCount = await _quotationOrderRepository.GetCountAsync(quotation.Id, null, null, null);

                if (orderCount > 0)
                    throw new UserFriendlyException($"销售报价单：{quotation.Number}已经关联销售订单，不允许反审核", "100000");
            }

            quotation.SetStatus(status);

            return quotation;
        }

        public async Task DeleteAsync(Guid id)
        {
            var quotation = await _repository.GetAsync(id, false);

            if (quotation == null)
                throw new UserFriendlyException($"销售报价单：{id}不存在", "100000");

            if (quotation.Status != DocumentStatusType.Creation)
                throw new UserFriendlyException($"销售报价单：{quotation.Number}非创建状态，不允许删除", "100000");

            await _repository.DeleteAsync(quotation.Id);
        }

        public async Task<Guid> PushOrderAsync(Guid id)
        {
            var quotation = await _repository.GetAsync(id, false);

            if (quotation == null)
                throw new UserFriendlyException($"销售报价单：{id}不存在", "100000");

            if(quotation.Status!= DocumentStatusType.Approved)
                throw new UserFriendlyException($"销售报价单：{quotation.Number}非审核状态，不允许下推销售订单", "100000");

            if (quotation.Items.IsNullOrEmpty())
                throw new UserFriendlyException($"销售报价单：{quotation.Number}没有明细，不能下推销售订单", "100000");

            var order = await _orderManager.GetAsync(null, DateTime.UtcNow, quotation.IncludeTax, quotation.CustomerId, quotation.Address, quotation.CurrencyId, quotation.ExchangeRate, null, null, null, "", SaleOrderType.Standard);

            var orderItems = new List<SaleOrderItem>();

            var quoationOrders = new List<SaleQuotationOrder>();

            foreach (var item in quotation.Items)
            {
                var orderItem = await _orderManager.GetItemAsync(null, item.ProductId, item.AuxiliaryUnitId, item.AuxiliaryQuantity, item.Price, item.TaxRateId, item.IsGift, "");

                orderItems.Add(orderItem);

                quoationOrders.Add(new SaleQuotationOrder(_guidGenerator.Create(), quotation.Id, item.Id, order.Id, orderItem.Id));
            }

            order.ChangeItems(orderItems);

            order = await _orderRepository.InsertAsync(order);

            await _quotationOrderRepository.InsertManyAsync(quoationOrders);

            return order.Id;
        }
    }
}
